package com.javasm.pk.service;

import com.javasm.pk.domain.GradeCodeRule;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 级次编码生成工具
 */
public class GradeCodeGenerator {
    //级次编码规则缓存
    private static final ConcurrentMap<String, GradeCodeRule> codeRuleMap = new ConcurrentHashMap<>();

    static PrimaryKeyService primaryKeyService;

    /**
     * 例如：2|2|2|2
     * 根据父编码获取下一个子编码
     * parentCode=01            第一次调用返回:0101，第二次调用返回:0102
     * parentCode=null || ""    第一次调用返回:01，第二次调用返回:02
     *
     * @param codeRule   编码规则
     * @param parentCode 父编码 可以为空
     * @param type       编码类型：业务名称
     * @return
     */
    public static String getNextCode(String codeRule, String parentCode, String type) {
        if (!codeRuleMap.containsKey(codeRule)) {
            codeRuleMap.putIfAbsent(codeRule, new GradeCodeRule(codeRule));
        }
        return createCode(codeRuleMap.get(codeRule), parentCode, type);
    }

    private static String createCode(GradeCodeRule gradeCodeRule, String parentCode, String type) {
        parentCode = parentCode == null || parentCode.isEmpty() ? "" : parentCode;
        int parentGrade = gradeCodeRule.getCodeGrade(parentCode);//父编码级次
        if (parentGrade < 0) {
            throw new IllegalArgumentException("parentCode(" + parentCode + ")跟codeRule(" + gradeCodeRule.getRule() + ")不匹配");
        }
        if (parentGrade >= gradeCodeRule.getMaxGradeCount()) {
            throw new IllegalArgumentException(parentCode + "已经是最末级编码，无法获取子编码！");
        }
//        int parentGradeLength = gradeCodeRule.getGradeLength(parentGrade);
        int subCodeSectionLength = gradeCodeRule.getSectionLength(parentGrade + 1);//子编码末级片段长度
        long nextSubCode = primaryKeyService.getLongKey(type + "-" + gradeCodeRule.getRule() + "-" + parentCode);
        String nextSubCodeStr = String.format("%0" + subCodeSectionLength + "d", nextSubCode);
        if (nextSubCodeStr.length() > subCodeSectionLength) {
            throw new IllegalArgumentException(parentCode + "的下一级编码已经用完！");
        }
        StringBuilder codeBuilder = new StringBuilder(parentCode);
        codeBuilder.append(nextSubCodeStr);
        return codeBuilder.toString();
    }

    static void setPrimaryKeyService(PrimaryKeyService primaryService) {
        primaryKeyService = primaryService;
    }

}
